/*
    经典课本题
*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define maxn 200001
#define INF 1e15

using namespace std;

int n;

struct node{    //特工和站点都用这个结构
    double x,y;
    bool isWhere;   //表示属性
}a[maxn],tmp[maxn];

bool high_sort(const node&a,const node&b){return a.y<b.y;}  //按照y值小到大排序

bool high_sort_(const node&a,const node&b){return (a.x<b.x)||((a.x==b.x)&&(a.y<b.y));}

double getDis(const node& a,const node& b){ //找到两个点后，计算距离
    double xx = a.x-b.x, yy = a.y-b.y;
    return sqrt (xx*xx + yy*yy);
}
double solve(int l,int r){
    double d=INF;
    if(l==r){
        return d;
    }
    if(r-l==1){
        if(a[l].isWhere^a[r].isWhere){  //不同属性点
            return getDis(a[l],a[r]);
        }
        else{
            return d;
        }
    }
    //开始二分
    int mid=(l+r)>>1;
    d=min(solve(l,mid),solve(mid+1,r)); //左边右边后，记录d与中间跨越的比
    int cnt=0;
    for(int i=l;i<=r;i++){
        if(fabs(a[mid].x-a[i].x)<d){    //首先，到中线距离小于d的才有后续比较资格
            tmp[cnt++]=a[i];
        }
    }
    sort(tmp,tmp+cnt,high_sort);    //对这些资格选手排序，此时用x了

    for(int i=0;i<cnt;i++){ //双层遍历
        for(int j=i+1;j<cnt&&tmp[j].y-tmp[i].y<d;j++){
            if(tmp[i].isWhere^tmp[j].isWhere){
                d=min(d,getDis(tmp[i],tmp[j]));
            }
        }
    }
    return d;
}
int main(void){
    int t;
    cin>>t;
    while(t--){
        cin>>n;
        for(int i=0;i<n;i++){
            scanf ("%lf%lf", &a[i].x, &a[i].y);
            a[i].isWhere=0;
        }
        for(int i=n;i<n+n;i++){
            scanf ("%lf%lf", &a[i].x, &a[i].y);
            a[i].isWhere=1;
        }
        n<<=1;  //n*2
        sort(a,a+n,high_sort_); //排序
        printf("%.3f\n",solve(0,n-1));
    }
    return 0;
}